<script setup lang='ts'>
import { ref, nextTick } from 'vue'
import { objectSpanMethod } from '@/utils/utils'
import { UploadProps, UploadRawFile } from 'element-plus'
import { ElMessage } from 'element-plus'
import { renderAsync } from 'docx-preview'

interface TableData {
  id: number
  type: string
  method: string
  url: string
}

const tableData = ref<TableData[]>([
  {
    id: 1,
    type: 'pdf',
    method: '内嵌 iframe',
    url: '/file/test.pdf'
  },
  {
    id: 2,
    type: 'docx',
    method: '插件 docx-preview',
    url: '/file/test.docx'
  },
  {
    id: 3,
    type: 'txt',
    method: '内嵌 iframe',
    url: '/file/test.txt'
  },
  {
    id: 4,
    type: 'mp4',
    method: 'Video标签',
    url: '/file/test.mp4'
  }
])

const type = ref<string>() // 预览类型
const url = ref<string>() // 预览地址
// 线上预览
const preview = async (fileUrl: string, fileType: string) => {
  switch (fileType) {
    case 'pdf':
      type.value = 'pdf'
      url.value = fileUrl
      break
    case 'docx':
      type.value = 'docx'
      await nextTick() // 等待dom更新完成
      const res = await fetch(fileUrl)
      const blob = await res.blob()
      renderAsync(
        blob, // 文件对象
        docxPreview.value, // dom容器
        docxPreview.value, // style容器
        { 
          className:'docx-container' // 自定义容器类名
        }
      )
      break
    case 'txt':
      type.value = 'txt'
      const txtRes = await fetch(fileUrl)
      const text = await txtRes.text() // 1. 获取文本内容
      const txtBlob = new Blob([text], { type: 'text/plain;charset=utf-8' }) // 2. 创建指定编码的 Blob
      url.value = URL.createObjectURL(txtBlob) // 3. 生成临时 URL 供 iframe 使用
      break
    case 'mp4':
      type.value = 'mp4'
      url.value = fileUrl
      break
    default:
      break
  }
}

// 线上下载
const download = async (fileUrl: string, fileType: string) => {
  const response = await fetch(fileUrl)
  const blob = await response.blob()
  const url = window.URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = `线上test.${fileType}` // 下载必须要有名字,不写后缀可能会下载格式错误
  document.body.appendChild(link)
  link.click()
  window.URL.revokeObjectURL(url)
  document.body.removeChild(link)
}

const docxPreview = ref()
// 本地预览
const preview2 = async (file: UploadRawFile, fileType: string) => {
  switch (fileType) {
    case 'pdf':
      type.value = 'pdf'
      url.value = URL.createObjectURL(file)
      break
    case 'docx':
      type.value = 'docx'
      await nextTick() // 等待dom更新完成
      renderAsync(
        file, // 文件对象
        docxPreview.value, // dom容器
        docxPreview.value, // style容器
        { 
          className:'docx-container' // 自定义容器类名
        }
      )
      break
    case 'txt':
      type.value = 'txt'
      const blob = new Blob([file], { type: 'text/plain;charset=utf-8' }) // 转换blob并调整编码
      url.value = URL.createObjectURL(blob) // 创建url
      break
    case 'mp4':
      type.value = 'mp4'
      url.value = URL.createObjectURL(file)
      break
    default:
      break
  }
  
}

// 上传文件前
const beforeUpload: UploadProps['beforeUpload'] = (files) => {
  const typeList = tableData.value.map(item => item.type)
  const fileType = files.name.split('.')[1]

  if (!typeList.includes(fileType)) {
    ElMessage.error('文件格式不支持')
    return false
  }
  preview2(files, fileType)
  return false // 阻止上传
}

// 本地文件下载
const download2 = (type: string) => {
  const fileUrl = `/file/test.${type}`
  const link = document.createElement('a')
  link.href = fileUrl
  link.download = `本地test.${type}`
  link.click()
}

</script>


<template>
  <div class="container">
    <el-table :data="tableData" border style="width: 100%; margin-top: 20px">
      <el-table-column prop="type" label="文件类型" width="180" />
      <el-table-column prop="method" label="预览方式" />
      <el-table-column label="线上文件预览">
        <template #default="{ row }">
          <el-button type="primary" size="small" plain @click="preview(row.url, row.type)">预览</el-button>
        </template>
      </el-table-column>
      <el-table-column label="线上文件下载">
        <template #default="{ row }">
          <el-button type="primary" size="small" plain @click="download(row.url, row.type)">下载</el-button>
        </template>
      </el-table-column>
      <el-table-column label="上传文件预览">
        <template #default>
          <el-upload
            ref="upload"
            class="upload-demo"
            action="#"
            :limit="1"
            :before-upload="beforeUpload"
          >
            <template #trigger>
              <el-button type="primary" size="small" plain>预览</el-button>
            </template>
          </el-upload>
        </template>
      </el-table-column>
      <el-table-column label="本地文件下载">
        <template #default="{ row }">
          <el-button type="primary" size="small" plain @click="download2(row.type)">下载</el-button>
        </template>
      </el-table-column>
    </el-table>

    <div class="show">
      <div v-if="!type" class="placeholder">预览区</div>
      <iframe
        v-if="type === 'pdf'"
        id="previewFrame"
        :src="url"
        class="iframe"
      />
      <div v-if="type === 'docx'" ref="docxPreview" class="docx-container" style="line-height: 3.15;" />
      <iframe
        v-if="type === 'txt'"
        id="previewFrame"
        :src="url"
        class="iframe"
      />
      <video
        v-if="type === 'mp4'"
        :src="url"
        class="iframe"
        controls
        autoplay
      />
    </div>
    <el-button @click="$router.back()" style="margin-top: 20px;">返回</el-button>
  </div>
</template>


<style scoped lang="scss">
  .container {
    width: 80%;
    padding: 50px 0;
    margin: 0 auto;
  }
  .show {
    width: 100%;
    height: 600px;
    margin-top: 20px;
    border: 1px solid #ccc;
    .placeholder{
      font-size: 40px;
      color: #ccc;
      user-select: none;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .iframe {
      width: 100%;
      height: 100%;
    }
  }

  :deep(.el-table .cell){
    height: 25px ;
  }

  .docx-container{
    width: inherit;
    height: inherit;
    overflow: auto;
  }
</style>